package com.heihei.transvideo;

import com.heihei.config.ConfigProperties;
import com.heihei.util.FileUtilF;
import org.apache.commons.collections4.CollectionUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 *  用于合并视频
 *
 * @author duanhf
 * 2022年07月26日 10:08:37
 */
public class MergeVideo {
    public static void main(String[] args) throws IOException {
        ConfigProperties.updateProperties();
//        start();
        startMergeTsVideo();
    }

    /**
     * 直接合并ts文件
     *
     * @author duanhf
     * 2022年07月28日 14:12:36
     */
    public static void startMergeTsVideo() throws IOException {
        StringBuilder sb = new StringBuilder();
        System.out.println("请输入有效的源文件夹：");
        File validSrcParentDir = FileUtilF.getValidSrcDir();
        File[] childFileArrOrigianl = validSrcParentDir.listFiles();
        if(childFileArrOrigianl == null || childFileArrOrigianl.length == 0) {
            System.out.println("文件为空");
            return;
        }
        List<File> allVideoFileList = getAllVideoFileList(childFileArrOrigianl);
        if(CollectionUtils.isEmpty(allVideoFileList)) {
            System.out.println("视频文件为空");
        }
        allVideoFileList.sort(new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        List<String> mergeAllList = new ArrayList<>();
        for (File file : allVideoFileList) {
            mergeAllList.add(file.getName());
        }
        //查看是否有间隔刷子文件，如果有，就加入到mergeAllList中
        addBrushStrListIfExists(mergeAllList, validSrcParentDir);
        //添加合并命令，并写入文件
        MergeAndWriteCommand2File(mergeAllList, sb, validSrcParentDir);
        System.out.println("已完成");
    }

    /**
     * 合并多个mp4文件（或者合并多个其他非ts格式的视频文件）
     *
     * @author duanhf
     * 2022年07月28日 13:51:11
     */
    public static void start() throws IOException {
        StringBuilder sb = new StringBuilder();
        System.out.println("请输入有效的源文件夹：");
        File validSrcParentDir = FileUtilF.getValidSrcDir();
        String tmpTsDirName = "tmp-ts-trans";
        File tmpTsDir = new File(validSrcParentDir, tmpTsDirName);
        if(!tmpTsDir.exists()) {
            tmpTsDir.mkdir();
        }

        File[] childFileArrOrigianl = validSrcParentDir.listFiles();
        if(childFileArrOrigianl == null || childFileArrOrigianl.length == 0) {
            System.out.println("文件为空");
            return;
        }
        List<File> childVideoList = getAllVideoFileList(childFileArrOrigianl);
        if(CollectionUtils.isEmpty(childVideoList)) {
            System.out.println("视频文件为空");
        }
        File[] childFileArr = new File[childVideoList.size()];
        childVideoList.toArray(childFileArr);

        Arrays.sort(childFileArr, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        for (File childFile : childFileArr) {
            //将该文件转为ts文件
            //ffmpeg -i test.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts 1.ts
            sb.append("\"").append(ConfigProperties.FFMPEG_HOME_DIR).append("\" -i \"")
                    .append(childFile.getName()).append("\" -c copy -bsf:v h264_mp4toannexb -f mpegts \"")
                    .append(tmpTsDirName).append("/").append(childFile.getName()).append(".ts").append("\"")
                    .append("\r\n");
        }

        //总的文件List
        List<String> mergeAllList = new ArrayList<>();
        //开始合并逻辑
        for (File file : childFileArr) {
            mergeAllList.add(tmpTsDirName + "/" + file.getName() + ".ts");
        }
        //查看是否有间隔刷子文件，如果有，那么就将刷子文件加入到 mergeAllList 中
        addBrushStrListIfExists(mergeAllList, validSrcParentDir);
        //添加合并命令，并写入文件
        MergeAndWriteCommand2File(mergeAllList, sb, validSrcParentDir);
        System.out.println("已完成");
    }

    /**
     * 添加合并命令，并写入文件
     *
     * @author duanhf
     * 2022年07月28日 14:08:58
     */
    private static void MergeAndWriteCommand2File(List<String> mergeAllList, StringBuilder sb, File validSrcParentDir) throws IOException {
        //开始合并命令
        addMergeCommand2Sb(sb, mergeAllList);
        sb.append("pause");
        File targetCmdFile = new File(validSrcParentDir, "ts-result-output.cmd");
        FileUtilF.writeTxtFile(sb.toString(), targetCmdFile, "GBK");
    }

    /**
     * 将合并命令，添加到 sb 中
     *
     * @author duanhf
     * 2022年07月28日 14:07:06
     */
    private static void addMergeCommand2Sb(StringBuilder sb, List<String> mergeAllList) {
        StringBuilder sbTsName = new StringBuilder();
        for (int i = 0; i < mergeAllList.size(); i++) {
            sbTsName.append(mergeAllList.get(i));
            if(i != mergeAllList.size() - 1) {
                sbTsName.append("|");
            }
        }
        //ffmpeg -i "concat:1.ts|2.ts" -c copy -bsf:a aac_adtstoasc -movflags +faststart ts.mp4
        sb.append("\"").append(ConfigProperties.FFMPEG_HOME_DIR).append("\" -i \"concat:")
                .append(sbTsName.toString()).append("\" -c copy -bsf:a aac_adtstoasc -movflags +faststart ts-result-output.mp4").append("\r\n");
    }


    /**
     * 查看是否有间隔刷子文件，如果有，那么就将刷子文件加入到 mergeAllList 中
     *
     * @author duanhf
     * 2022年07月28日 14:03:43
     */
    private static void addBrushStrListIfExists(List<String> mergeAllList, File validSrcParentDir) {
        //记录过度笔刷
        String brushesDirName = "Brushes";
        File brushesDir = new File(validSrcParentDir, brushesDirName);
        List<String> brushStrList = new ArrayList<>();
        //ffmpeg -i "concat:1.ts|2.ts" -c copy -bsf:a aac_adtstoasc -movflags +faststart ts.mp4
        if(brushesDir.exists()) {
            File[] brushesArr = brushesDir.listFiles();
            if(brushesArr != null && brushesArr.length > 0) {
                for (File file : brushesArr) {
                    brushStrList.add(brushesDirName + "/" + file.getName());
                }
            }
        }
        if(CollectionUtils.isNotEmpty(brushStrList)) {
            int mergeAllFlag = 1;
            int brushFlag = 0;
            while (mergeAllFlag < mergeAllList.size()) {
                String currBrushStr = brushStrList.get(brushFlag);
                brushFlag++;
                if(brushFlag >= brushStrList.size()) {
                    brushFlag = 0;
                }
                //像mergeAllList中增加笔刷过度
                mergeAllList.add(mergeAllFlag, currBrushStr);
                mergeAllFlag += 2;
            }
        }
    }

    /**
     * 从数组中，获取视频文件，组成List，并返回
     *
     * @author duanhf
     * 2022年07月28日 13:53:50
     */
    private static List<File> getAllVideoFileList(File[] childFileArrOrigianl) {
        List<File> childVideoList = new ArrayList<>();
        for (File file : childFileArrOrigianl) {
            if(FileUtilF.isVideo(file)) {
                childVideoList.add(file);
            }
        }
        return childVideoList;
    }
}
